﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace Star.Tools.Excel.Attributes
{
    public static class ExcelColumnAttributeHelper
    {
        /// <summary>
        /// 列头list
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static List<string> GetColumnNames<T>()
        {
            List<string> titleList = new List<string>();
            var PropertyInfo = typeof(T).GetExcelColumns();
            foreach (var property in PropertyInfo)
            {
                var attrs = property.GetCustomAttributes(typeof(ExcelColumnAttribute), true);
               // var ignore = attrs.OfType<ExcelColumnAttribute>().FirstOrDefault();
                foreach (var attr in attrs)
                {

                    ExcelColumnAttribute authAttr = attr as ExcelColumnAttribute;
                    if (authAttr != null)
                    {
                        var titleName = property.GetColumnName();
                        if (!property.GetIsIgnore() && property.GetCustomAttributes(typeof(ExcelColumnAttribute), true).Length > 0)
                        {
                            titleList.Add(titleName);
                        }
                    }
                }

            }
            return titleList;
        }

        public static List<PropertyInfo> GetExcelColumns(this Type type)
        {
            List<PropertyInfo> propertyInfos = new List<PropertyInfo>();

            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                object[] attrs = propertyInfo.GetCustomAttributes(typeof(ExcelColumnAttribute), true);
                foreach (object attr in attrs)
                {
                    ExcelColumnAttribute authAttr = attr as ExcelColumnAttribute;
                    if (authAttr != null)
                    {
                        propertyInfos.Add(propertyInfo);
                    }
                }
            }


            return propertyInfos;

            //model = model.OrderBy(it =>
            //(it.GetCustomAttributes(true).Where(t => t.GetType() == typeof(ExcelColumnAttribute)).Single() as ExcelColumnAttribute).Order).ToList();

        }


        /// <summary>
        /// 获取属性列名
        /// </summary>
        /// <param name="memberInfo"></param>
        /// <returns></returns>
        public static string GetColumnName(this MemberInfo memberInfo)
        {
            string titleName = string.Empty;
            var attribute = memberInfo.GetCustomAttributes(typeof(ExcelColumnAttribute), false).FirstOrDefault();
            if (attribute != null)
            {

                titleName = (attribute as ExcelColumnAttribute).ColumnName ?? memberInfo.Name;
            }
            else
            {
                titleName = memberInfo.Name;
            }

            return titleName;
        }


        /// <summary>
        /// 获取忽视属性
        /// </summary>
        /// <param name="memberInfo"></param>
        /// <returns></returns>
        public static bool GetIsIgnore(this MemberInfo memberInfo)
        {
            bool IsIgnore = false;
            var attribute = memberInfo.GetCustomAttributes(typeof(ExcelColumnAttribute), false).FirstOrDefault();
            if (attribute != null)
            {
                IsIgnore = (attribute as ExcelColumnAttribute).IsIgnore;
            }
            return IsIgnore;
        }

        public static ExcelCellStyleEnum GetExcelCellStyleEnum(this MemberInfo memberInfo)
        {
            var attribute = memberInfo.GetCustomAttributes(typeof(ExcelColumnAttribute), false).FirstOrDefault();
            if (attribute != null)
            {
                return   (attribute as ExcelColumnAttribute).ExcelCellStyle;
               // Enum.GetValues(ExcelCellStyleEnum)
            }
            return ExcelCellStyleEnum.center;
        }
        private static Dictionary<PropertyInfo, ExcelColumnAttribute> GetPropInfo<T>()
        {
            Dictionary<PropertyInfo, ExcelColumnAttribute> _infos = new Dictionary<PropertyInfo, ExcelColumnAttribute>();
            // Type _type = typeof(T);
            PropertyInfo[] _propInfos = typeof(T).GetProperties();
            foreach (var propInfo in _propInfos)
            {
                object[] objAttrs = propInfo.GetCustomAttributes(typeof(ExcelColumnAttribute), true);
                if (objAttrs.Length > 0)
                {
                    ExcelColumnAttribute attr = objAttrs[0] as ExcelColumnAttribute;
                    if (attr != null)
                    {
                        _infos.Add(propInfo, attr);
                    }
                }
            }
            return _infos;
        }
        private static void MakePropertyInfo(List<PropertyInfo> properties, ref Type[] propertyTypes, ref List<int> hideColumns,
        ref ExcelColumnAttribute[] ColumnAttributes, int startFieldNum, int endFieldNum)
        {
            int propertyCount = properties.Count;
            for (int k = 0; k < propertyCount; k++)
            {
                if (k >= startFieldNum - 1 && k <= endFieldNum - 1)
                {
                    PropertyInfo p = properties[k];
                    //if (p.GetCustomAttributes(typeof(DisplayHide), true).Cast<DisplayHide>().FirstOrDefault() != null)
                    //    hideColumns.Add(k);
                    ColumnAttributes[k] =
                        p.GetCustomAttributes(typeof(ExcelColumnAttribute), true)
                            .Cast<ExcelColumnAttribute>()
                            .FirstOrDefault();

                    propertyTypes[k] = p.PropertyType;
                }
                else
                {
                    hideColumns.Add(k);
                }
            }
        }


    }

    public static class ExcelModelsPropertyManage
    {
        private static readonly Dictionary<String, IList<PropertyInfoDetail>> PropertyInfos;

        private static readonly Dictionary<String, Object> ExtendedDefaultValue;

        static ExcelModelsPropertyManage()
        {
            PropertyInfos = new Dictionary<String, IList<PropertyInfoDetail>>();

            ExtendedDefaultValue = new Dictionary<String, Object>();
        }

        #region 获取属性列表
        public static IList<PropertyInfoDetail> CreatePropertyInfos(Type t)
        {
            String name = t.Name;

            if (PropertyInfos.ContainsKey(name))
            {
                return PropertyInfos[name];
            }

            PropertyInfo[] ps = t.GetProperties();

            List<PropertyInfoDetail> checkPropertyInfos = new List<PropertyInfoDetail>();

            foreach (var item in ps)
            {
                Object[] d = item.GetCustomAttributes(false);

                if (d.Any(s => s.GetType() == typeof(IgnoreAttribute)))
                {
                    continue;
                }

                DefaultValueAttribute dv = d.SingleOrDefault(s => s.GetType() == typeof(DefaultValueAttribute)) as DefaultValueAttribute;

                checkPropertyInfos.Add(new PropertyInfoDetail() { PropertyInfoV = item, DefaultVale = dv == null ? null : dv.Value });
            }

            PropertyInfos.Add(name, checkPropertyInfos);

            return checkPropertyInfos;
        }
        #endregion

        public static Object GetExtendedDefaultValue(Type t)
        {
            String name = t.Name;

            if (ExtendedDefaultValue.ContainsKey(name))
            {
                return ExtendedDefaultValue[name];
            }



            PropertyInfo p = t.GetProperties().SingleOrDefault(s => s.Name == "TypeValue");

            if (p == null)
            {
                return null;
            }

            DefaultValueAttribute dv = p.GetCustomAttributes(typeof(DefaultValueAttribute), false).SingleOrDefault() as DefaultValueAttribute;

            Object v = dv == null ? null : dv.Value;

            ExtendedDefaultValue.Add(name, v);

            return v;


        }
    }

    public class PropertyInfoDetail
    {
        public PropertyInfo PropertyInfoV { get; set; }

        public Object DefaultVale { set; get; }
    }
}
